package com.yzq.utils;

import cn.hutool.core.util.NumberUtil;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yzq.model.dto.picture.PictureAnalysisResult;
import darabonba.core.exception.ClientException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Component
public class AliyunOSSUtils {
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName; // 存储空间名称
    @Value("${aliyun.oss.region}")
    private String region;

    /**
     * 上传文件到阿里云OSS
     * @param content 文件字节数组
     * @param originalFilename 原始文件名
     * @param spaceId //图片类别 0-公共图库 - spaceId私有图库
     * @return 返回地址
     * @throws Exception
     */
    public String upload(byte[] content, String originalFilename, Long spaceId) throws Exception {
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();


        //获取当前系统日期的字符串,格式为 yyyy_MM_dd
        //设置公共图库和私有图库
        String pictureCategory = spaceId == 0 ? "public" : String.format("space/%s", spaceId);

        String pictureDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd"));
        //生成一个新的不重复的文件名
        String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = pictureCategory + "/" + pictureDate + "_" + newFileName;

        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
        } finally {
            ossClient.shutdown();
        }

        return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }

    /**
     * 获取图片信息
     * @param url 图片地址
     * @return 图片信息
     * @throws ClientException 如果获取图片信息失败
     */
    public PictureAnalysisResult getImage(String url) throws ClientException {
        OSS ossClient = null;
        try {
            // 解析URL获取bucketName和key
            URI uri = new URI(url);
            String host = uri.getHost();
            String path = uri.getPath().substring(1);
            String[] hostParts = host.split("\\.");
            String bucketName = hostParts[0];

            // 创建OSS客户端
            EnvironmentVariableCredentialsProvider credentialsProvider =
                    CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            ossClient = OSSClientBuilder.create()
                    .endpoint(endpoint)
                    .credentialsProvider(credentialsProvider)
                    .build();

            // 构建获取图片信息的请求
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, path);
            getObjectRequest.setProcess("image/info");

            // 获取OSSObject
            OSSObject ossObject = ossClient.getObject(getObjectRequest);

            // 读取图片信息到字符串
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = ossObject.getObjectContent().read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            String imageInfoJson = baos.toString("UTF-8");

            // 解析JSON
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(imageInfoJson);

            // 提取图片信息
            long picSize = rootNode.path("FileSize").path("value").asLong();
            int picWidth = rootNode.path("ImageWidth").path("value").asInt();
            int picHeight = rootNode.path("ImageHeight").path("value").asInt();
            String picFormat = rootNode.path("Format").path("value").asText();

            // 计算宽高比（保留 2位小数）
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

            // 提取文件名
            String picName = path.substring(path.lastIndexOf("/") + 1);

            // 填充PictureAnalysisResult
            PictureAnalysisResult result = new PictureAnalysisResult();
            result.setUrl(url);
            result.setPicName(picName);
            result.setPicSize(picSize);
            result.setPicWidth(picWidth);
            result.setPicHeight(picHeight);
            result.setPicScale(picScale);
            result.setPicFormat(picFormat);
            result.setThumbnailUrl(url + "?x-oss-process=image/quality,q_60");


            return result;

        } catch (URISyntaxException e) {
            throw new ClientException("无效的URL格式: " + e.getMessage());
        } catch (IOException e) {
            throw new ClientException("读取或解析图片信息失败: " + e.getMessage());
        } catch (Exception e) {
            throw new ClientException("未知错误: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 删除OSS上的指定文件
     * @param url 待删除文件的URL（与上传返回的URL格式一致）
     * @throws ClientException 若删除过程中发生错误（如权限不足、文件不存在等）
     */
    public void deleteFile(String url) throws ClientException {
        OSS ossClient = null;
        try {
            // 解析URL获取bucketName和objectName（文件在OSS中的完整路径）
            URI uri = new URI(url);
            String host = uri.getHost();
            String path = uri.getPath().substring(1); // 去除路径开头的斜杠
            String[] hostParts = host.split("\\.");
            String bucketName = hostParts[0]; // 从主机名提取bucket名称

            // 创建OSS客户端（复用上传方法中的配置，使用V4签名）
            EnvironmentVariableCredentialsProvider credentialsProvider =
                    CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

            ossClient = OSSClientBuilder.create()
                    .endpoint(endpoint)
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region(region)
                    .build();

            // 执行删除操作
            ossClient.deleteObject(bucketName, path);

        } catch (URISyntaxException e) {
            throw new ClientException("无效的文件URL格式，请检查URL是否正确: " + e.getMessage());
        } catch (Exception e) {
            // 捕获OSS服务端异常（如文件不存在、权限不足）和客户端异常（如网络问题）
            throw new ClientException("删除文件失败: " + e.getMessage());
        } finally {
            // 确保客户端资源释放
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
